#include "gameloc.h"
#include <QListView>
#include <QRadioButton>
#include <QProgressBar>
#include <QDebug>
#include <QFileDialog>

Gameloc::Gameloc(bool weHaveArgument, QString fileToOpen, QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    show();

    #ifdef Q_OS_WIN32
        os_windows = true;
    #endif

    #ifdef Q_OS_LINUX
         os_windows = false;
    #endif

    if( os_windows )    // На линупсе тема выглядит ужасно
        setStyleSheet(readStyleSheet(":/themes/dark_orange_metal/dark_orange_metal.qss"));

    setup_FileTree_and_folderTree_ContextMenu();
    setup_toolBar();

    if( !weHaveArgument )
    {
        ui->saveAction->setEnabled(false);      // Если на момент запуска ни один проект не открыт
        ui->saveAsAction->setEnabled(false);    // делаем опции "Сохранить" и "Сохранить как..." недоступными
    }
    playerAndRecorder = new Audio();

    t = new QTimer();
    t->start(1);

    update_window_size_timer = new QTimer();     // Таймер используемый для постоянного обновления вида таблицы переозвучки и таблицы файлов
    update_window_size_timer->start(1);

    connect( update_window_size_timer, SIGNAL(timeout()), SLOT(updateTablesViewOnResize()));

    // Загрузка настроек из реестра
    readSettings();
    updateRecentFileActions();

    if( os_windows )
        userName = QString::fromLocal8Bit (qgetenv ("USERNAME").constData ()).toUtf8();
    else
        userName = QString::fromLocal8Bit( qgetenv("USER").constData()).toUtf8();

    // Установка начальных значений переменным
    version = "0.9.0_beta";     // Менять первое число при крупных изменениях
                                // Менять второе число при добавлении функций и изменениях интерфейса
                                // Менять третье число при исправлениях ошибок

    setWindowTitle("GameLOC " + version);

    activeGLR = NULL; // Устанавливаем адрес в ноль, чтобы было возможно проверить указатель на "ссылаемость не на что"

    gameloc_tempFolders_path = QDir::homePath() + "/gameloc_tempFolders";

    pathToLastAddedRevoice = QDir::homePath();


    connect(ui->fileTree,      SIGNAL(itemClicked(QTreeWidgetItem*,int)),
                               SLOT  (updateRevoicesTable_on_currentSoundChanged(QTreeWidgetItem*)));

    connect(ui->folderTree,    SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
                               SLOT(clearRevoiceTable()));

    connect(ui->folderTree,    SIGNAL(itemClicked(QTreeWidgetItem*,int)), new Folder(NULL, "", ui), SLOT(showFilesInTree(QTreeWidgetItem*)));

    connect(ui->folderTree,    SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(setActiveGLR(QTreeWidgetItem*)));

    connect(ui->revoicesTable, SIGNAL(currentCellChanged(int,int,int,int)), this, SLOT(loadRevoiceOnSelect(int)));
    connect(ui->revoicesTable, SIGNAL(cellChanged(int,int)), SLOT(cellEdited(int, int)));

    connect( playerAndRecorder, SIGNAL(playEnded()), this, SLOT(on_playEnded()));
    connect( playerAndRecorder, SIGNAL(playStoped()), this, SLOT(on_playEnded()));

    connect( searchField, SIGNAL(textChanged(QString)), SLOT(checkAvailabilityOfSearchRequest()));

    // Подзаголовочное меню
    connect( ui->openAnotherAction,     SIGNAL(triggered()), SLOT(openProjectFromFile()));
    connect( ui->exportToFolder_action, SIGNAL(triggered()), SLOT(prepareTo_ExportToFolder()));

    // Нажатия кнопок
    connect( ui->addSoundButton,    SIGNAL(clicked()),     SLOT(addRevoiceFromFolder()));
    connect( ui->deleteSoundButton, SIGNAL(clicked()),     SLOT(deleteRevoice()));
    connect( ui->recordNewButton,   SIGNAL(toggled(bool)), SLOT(recordNewRevoice(bool)));
    connect( ui->rerecordButton,    SIGNAL(toggled(bool)), SLOT(rerecordRevoice(bool)));
    connect( ui->repeatButton,      SIGNAL(toggled(bool)), SLOT(reopenRevoice()));

    // Если программе были даны параметры
    if( weHaveArgument )
    {
        archiveToExtract = new QString(fileToOpen);

        progressDialog = new ProgressDialog(this);
        progressDialog->show();
        progressDialog->hideFullProgress();
        progressDialog->hideProgress();
        progressDialog->setText("Распаковка и открытие файла " + getFileNameFromPath(fileToOpen));
        progressDialog->setTitle("Открытие " + getFileNameFromPath(fileToOpen));

        t = new QTimer();
        t->start(1);
        connect( t, SIGNAL(timeout()), SLOT(extractArchiveOnOpen()));
    }
}

void Gameloc::setup_FileTree_and_folderTree_ContextMenu()
{
    //-----------------------  FolderTree  -----------------------//

    folderTree_changeProperties_action   = new QAction("Изменить свойства папки", ui->folderTree);
    folderTree_showStatistic_action      = new QAction("Показать статистику проекта", ui->folderTree);

    folderTree_clearMenu                 = new QMenu(ui->folderTree);
    folderTree_clearAction               = new QAction("Очистить содержимое папки от", ui->folderTree);;
    folderTree_clearRevoices_action      = new QAction("вариантов переозвучки", ui->folderTree);
    folderTree_clearText_action          = new QAction("текста озвучивания", ui->folderTree);
    folderTree_clearAll_action           = new QAction("вариантов переозвучки и текстов перевода", ui->folderTree);
    folderTree_closeActivePrj_action     = new QAction("Закрыть проект", ui->folderTree);

    QList <QAction *> clearActions;
    clearActions << folderTree_clearRevoices_action
                << folderTree_clearText_action
                << folderTree_clearAll_action;

    folderTree_clearMenu->addActions(clearActions);
    folderTree_clearAction->setMenu(folderTree_clearMenu);

    ui->folderTree->addAction(folderTree_closeActivePrj_action);
    ui->folderTree->addAction(folderTree_showStatistic_action);
    ui->folderTree->addAction(folderTree_clearAction);
    ui->folderTree->addAction(folderTree_changeProperties_action);

    ui->folderTree->setContextMenuPolicy(Qt::ActionsContextMenu);

    folderTree_clearAction->setEnabled(false);
    folderTree_closeActivePrj_action->setEnabled(false);
    folderTree_showStatistic_action->setEnabled(false);
    folderTree_changeProperties_action->setEnabled(false);

    connect(folderTree_changeProperties_action, SIGNAL(triggered()), SLOT(on_editFolderProperties()));

    connect(folderTree_clearText_action,     SIGNAL(triggered()), SLOT(clearFolder_texts()));
    connect(folderTree_clearRevoices_action, SIGNAL(triggered()), SLOT(clearFolder_revoices()));
    connect(folderTree_clearAll_action,      SIGNAL(triggered()), SLOT(clearFolder_all()));

    //-----------------------  FileTree  ------------------------//
    fileTree_changeProperties_action = new QAction("Изменить свойства файла", ui->fileTree);
    fileTree_clearAction             = new QAction("Очистить от", ui->fileTree);

    fileTree_clearMenu = new QMenu(ui->fileTree);
    fileTree_clearAction->setMenu(fileTree_clearMenu);
    fileTree_clearRevoices_action    = fileTree_clearMenu->addAction("переозвучек");
    fileTree_clearText_action        = fileTree_clearMenu->addAction("текста перевода");
    fileTree_clearAll_action         = fileTree_clearMenu->addAction("всего");

    ui->fileTree->addAction(fileTree_clearAction);
    ui->fileTree->addAction(fileTree_changeProperties_action);

    ui->fileTree->setContextMenuPolicy(Qt::ActionsContextMenu);

    fileTree_changeProperties_action->setEnabled(false);
    fileTree_clearAction->setEnabled(false);

    connect( fileTree_clearAll_action,      SIGNAL(triggered()), SLOT(clearSound_all()));
    connect( fileTree_clearRevoices_action, SIGNAL(triggered()), SLOT(clearSound_revoices()));
    connect( fileTree_clearText_action,     SIGNAL(triggered()), SLOT(clearSound_text()));
    connect( fileTree_changeProperties_action, SIGNAL(triggered()), SLOT(editSoundProperties()));
}

void Gameloc::setup_toolBar()
{
    searchField = new QLineEdit;
    searchAction = new QAction(QIcon(":/icons/search.png"), "", this);
    advancedSearchParamsAction = new QAction(QIcon(":icons/advancedSearchParams.png"), "", this);

    ui->toolBar->addActions( QList <QAction*> () << ui->newFileAction
                                                 << ui->openAnotherAction
                                                 << ui->saveAction
                                                 << ui->saveAsAction);
    ui->toolBar->addSeparator();
    ui->toolBar->addWidget( new QLabel("Поиск файлов:"));
    ui->toolBar->addWidget(searchField);
    ui->toolBar->addActions( QList <QAction*> () << searchAction << advancedSearchParamsAction);

    searchNext_mode = false;

    searchAction->setEnabled(false);
    advancedSearchParamsAction->setEnabled(false);
    searchField->setEnabled(false);

    connect( searchAction, SIGNAL(triggered()), SLOT(search_fromMainWindow()));
    connect( searchField, SIGNAL(textChanged(QString)), SLOT(searchTextChanged()));
    connect( advancedSearchParamsAction, SIGNAL(triggered()),SLOT(on_advancedSearchParamsAction_triggered()));
}

QString Gameloc::readStyleSheet(QString fileName)
{
    QString css;
    QFile file(fileName);

    if( file.open(QFile::ReadOnly) )
        css = file.readAll();
    else
        QMessageBox::information(this, "Ошибка", "Не удалось загрузить тему");
    file.close();
    return css;
}

void Gameloc::updateTablesViewOnResize()
{
    // Настройка ширины столбцов таблицы переозвучки
    ui->revoicesTable->setColumnWidth(2, 50);
    ui->revoicesTable->setColumnWidth(3, 30);                                                                   // У этих столбцов ширина постоянная

    ui->revoicesTable->setColumnWidth(1, (ui->revoicesTable->width() - ui->revoicesTable->columnWidth(2) -
                                                               ui->revoicesTable->columnWidth(3)) / 3);

    ui->revoicesTable->setColumnWidth(0, ui->revoicesTable->width() - ui->revoicesTable->columnWidth(1) -
                                                              ui->revoicesTable->columnWidth(2) -
                                                              ui->revoicesTable->columnWidth(3) - 2);           // А у этих динамическая
    // Настройка ширины столбцов списка файлов
    ui->fileTree->setColumnWidth(1,20);
    ui->fileTree->setColumnWidth(2,20);
    ui->fileTree->setColumnWidth(0, ui->fileTree->width() - 70);
}

void Gameloc::openFromTempPath( QString tempPath, bool fromGLR )
{
    qDebug() << "Gameloc::openFromTempPath: Открываю распакованный GLR из папки " << tempPath;

    if( QDir::setCurrent(tempPath))
    {
        GLR* currentLoadingGLR = new GLR(tempPath, ui, &version);

        if( currentLoadingGLR->loadInfo())
        {            
            ui->folderTree->addTopLevelItem(currentLoadingGLR);

            openedFiles.push_back(currentLoadingGLR);

            ui->saveAction->setEnabled(true);
            ui->saveAsAction->setEnabled(true);

            if( fromGLR )
                currentLoadingGLR->setPathToSave( *archiveToExtract );

            folderTree_clearAction->setEnabled(true);
            folderTree_closeActivePrj_action->setEnabled(true);
            folderTree_showStatistic_action->setEnabled(true);
            folderTree_changeProperties_action->setEnabled(true);

            searchAction->setEnabled(true);
            advancedSearchParamsAction->setEnabled(true);
            searchField->setEnabled(true);

            setActiveGLR(currentLoadingGLR);
        }
        else
        {
            delete currentLoadingGLR;
            activeGLR = NULL;

            QDir::setCurrent(programPath);

            QDir *d = new QDir;
            d->setPath(tempPath);
            d->removeRecursively();

            delete d;
        }
    }
    else
    {
        QMessageBox::critical(this, "Ошибка", tr("Не удалось зайти во временную папку\n%1").arg(tempPath));
    }

    progressDialog->close();
    delete progressDialog;
}

void Gameloc::openProjectFromFile()
{
    QString* fileName = new QString( QFileDialog::getOpenFileName(this, "Открыть файл GLR", QDir::homePath(), "Файл проекта Gameloc (*.glr)" ));

    if( !fileName->isEmpty())
    {
        archiveToExtract = new QString(*fileName);

        progressDialog = new ProgressDialog(this);
        progressDialog->show();
        progressDialog->hideFullProgress();

        progressDialog->setText("Распаковка архива");
        progressDialog->setTitle("Открытие " + getFileNameFromPath(*fileName));

        t->start(1);
        connect( t, SIGNAL(timeout()), SLOT(extractArchiveOnOpen()));
   }

    delete fileName;
}

void Gameloc::extractArchiveOnOpen()
{
    qDebug() << "Gameloc::extractArchiveOnOpen: Вызвана функция для распаковки архива";
    arc_7zr = new QProcess;

    bool alreadyInRecentFiles = false;
    for( int i = 0; i < recentFiles.count(); i++)
        if( *archiveToExtract == recentFiles.at(i))
            alreadyInRecentFiles = true;

    if( ! alreadyInRecentFiles )
    {
        recentFiles << *archiveToExtract;
        updateRecentFileActions();
    }

    QString *pathToExtract = new QString( gameloc_tempFolders_path + "/" + getFileNameFromPath( *archiveToExtract ) );

    QDir *d = new QDir;
    d->mkpath(*pathToExtract);
    delete d;

    arc_7zr->start(tr("arc x -o+ -dip -dp\"%1\" \"%2\"")
                   .arg( *pathToExtract )
                   .arg( *archiveToExtract ));

    if( ! arc_7zr->waitForStarted())
    {
        progressDialog->close();
        delete progressDialog;
        QMessageBox::critical(this, "Ошибка!",
                           tr("Не удалось запустить FreeArc для распаковки GLR-файла\n " \
                              "Была попытка запустить FreeArc из %1").arg(programPath));
    }
    delete pathToExtract;

    ui->saveAction->setEnabled(true);
    ui->saveAsAction->setEnabled(true);

    disconnect( t, SIGNAL(timeout()), this, SLOT(extractArchiveOnOpen()));
    connect( t, SIGNAL(timeout()), SLOT(updateProgressWhileExtracting()));
}

void Gameloc::updateProgressWhileExtracting()
{
    QString printedData;
    int progress = 0;

    if( ! progressDialog->progressVisible() )
        progressDialog->showProgress();

    if( arc_7zr->state() == QProcess::NotRunning )
    {
        QString *pathToExtract = new QString( gameloc_tempFolders_path + "/" + getFileNameFromPath( *archiveToExtract ) );

        progressDialog->setText("Открытие проекта");
        progressDialog->hideProgress();

        qDebug() << "Gameloc::extractArchiveOnOpen: Arc закончил свою работу. Вывод: " << arc_7zr->readAll();
        openFromTempPath(*pathToExtract, true);

        disconnect( t, SIGNAL(timeout()), this, SLOT(updateProgressWhileExtracting()));
        delete arc_7zr;
    }
    else
    {
        printedData = arc_7zr->readLine();
        if( printedData.contains("ERROR:"))
        {
            QMessageBox::critical(this, "Ошибка FreeArc", tr("Во время архивации произошла ошибка: %1").arg(printedData));
        }

        printedData = printedData.remove("\010").remove("%").trimmed();

        if( !printedData.isEmpty())
        {
            progress = (int) printedData.right(5).left(4).toFloat();
            qDebug() << printedData << " | " << progress;
            progressDialog->setProgress(progress);
        }
    }
}

void Gameloc::loadRevoiceOnSelect(int row)
{
    // BUG: При перемещении по списку стрелками таблица и текст не обновляются
    qDebug() << "Gameloc::loadRevoiceOnSelect(): Выбран вариант озвучки.";
    qDebug() << "Gameloc::loadRevoiceOnSelect(): Открываю файл в playerAndRecorder для работы с ним";

    Revoice *selectedRevoice  = NULL;
    int      indexOfSelectedRevoice = row - 1;       // Индекс = строка - 1, потому что в таблице еще есть строка для доступа к оригинальной озвучке

    if( playerAndRecorder->isOpened())
    {
        if( playerAndRecorder->isPlaying())
        {
            qDebug() << "Gameloc::loadRevoiceOnSelect(): Останавливаю воспроизведение";
            playerAndRecorder->stopPlay();
        }

        playerAndRecorder->closeFile();
        qDebug() << "Gameloc::loadRevoiceOnSelect(): Бывший открытым в playerAndRecorder файл закрыт. Память высвобождена";
    }

    if( indexOfSelectedRevoice >= 0)    // Если индекс положителен, значит выбран вариант переозвучки
    {        
        ui->deleteSoundButton->setEnabled(true);
        ui->rerecordButton->setEnabled(true);

        qDebug() << tr("Gameloc::loadRevoiceOnSelect(): indexOfSelectedRevoice = %1." \
                       "Это значит что в playerAndRecorder надо открывать переозвучку").arg(indexOfSelectedRevoice);

        selectedRevoice = activeSound->getRevoice(indexOfSelectedRevoice);

        if( playerAndRecorder->openFile( selectedRevoice->getPath(), ui->repeatButton->isChecked() ))
        {
            qDebug() << "Gameloc::loadRevoiceOnSelect(): Файл успешно загружен, настраиваю морду";

            ui->timeLabel ->setText( tr("00:00/") + playerAndRecorder->getLenAsStr() );
            ui->timeScroll->setMaximum( playerAndRecorder->getLenInSec());
        }
        else
        {
            qDebug() << "Gameloc::loadRevoiceOnSelect(): Неудалось загрузить файл";
            QMessageBox::critical(this, "Ошибка", "Ошибка загрузки файла");
        }
    }
    else    // Если индекс отрицателен, значит выбран оригинальный файл
    {
        ui->deleteSoundButton->setDisabled(true);
        ui->rerecordButton->setDisabled(true);

        qDebug() << tr("Gameloc::loadRevoiceOnSelect(): indexOfSelectedRevoice = %1." \
                       "Это значит что в playerAndRecorder надо открывать оригинальный файл").arg(indexOfSelectedRevoice);

        if( playerAndRecorder->openFile( activeSound->getPathToOrig(), ui->repeatButton->isChecked() ))
        {
            qDebug() << "Gameloc::loadRevoiceOnSelect(): Файл успешно загружен, настраиваю морду";

            ui->timeLabel ->setText( tr("00:00/") + playerAndRecorder->getLenAsStr() );
            ui->timeScroll->setMaximum( playerAndRecorder->getLenInSec());
        }
        else
        {
            qDebug() << "Gameloc::loadRevoiceOnSelect(): Неудалось загрузить файл";
            QMessageBox::critical(this, "Ошибка", "Ошибка загрузки файла");
        }
    }
}

void Gameloc::setActiveGLR( QTreeWidgetItem* newActiveGLR)
{
    GLR* glr = (GLR*) newActiveGLR;

    if( glr->getType() == "GLR")
    {
        if( activeGLR)
            activeGLR->setFont(0, QFont());

        activeGLR = glr;
        activeGLR->setFont(0, QFont(activeGLR->font(0).family(), -1, QFont::Bold, false));
    }
    else
        setActiveGLR( glr->parent());
}

void Gameloc::on_playButton_toggled( bool checked )
{
    if( checked )           // Если кнопка стала активной
    {
        playerAndRecorder->startPlay( ui->repeatButton->isChecked() );
        connect( t, SIGNAL(timeout()), this, SLOT(updateWidgets_onPlay()));
    }
    else                    // Если кнопка стала неактивной
    {
        if( playerAndRecorder->isPlaying())
        {
            playerAndRecorder->pausePlay();
            disconnect( t, SIGNAL(timeout()), this, SLOT(updateWidgets_onPlay()));
        }
    }
}

void Gameloc::on_stopButton_clicked()
{
    playerAndRecorder->stopPlay();                                                        // Остановка воспроизведения
    ui->playButton->setChecked(false);                                      // Делаем неактивной кнопку воспроизведения
    disconnect( t, SIGNAL(timeout()), this, SLOT(updateWidgets_onPlay()));

    updateWidgets_onPlay();
}

void Gameloc::updateWidgets_onPlay()
{
    ui->timeScroll->setValue( playerAndRecorder->reqCurPos());
    ui->timeLabel->setText( tr("%1/%2").arg( playerAndRecorder->getCurAsStr() )
                                       .arg( playerAndRecorder->getLenAsStr()));
}

void Gameloc::on_newFileAction_triggered()
{
    newFileDialog = new NewFileDialog(this);
    newFileDialog->show();

    connect( newFileDialog, SIGNAL(accepted()), this, SLOT(cnf_start()) );
}

void Gameloc::on_saveAction_triggered()
{
    if( ! activeGLR->hasSavePath() )
        activeGLR->setPathToSave( QFileDialog::getSaveFileName(this,
                                                               "Выберите путь для сохранения файла GLR",
                                                               QDir::homePath() ,
                                                               "Файл проекта Gameloc (*.glr)"));

    if( activeGLR->hasSavePath()) // Если при выборе пути сохранения, пользователь не нажал на отмену
    {
        save_start();
    }
}

void Gameloc::on_saveAsAction_triggered()            // Если выбран пункт меню "Сохранить как"
{
    QString pathToSave = QFileDialog::getSaveFileName(this,
                                                      "Выберите путь для сохранения файла GLR",
                                                      QDir::homePath(),
                                                      "Файл проекта Gameloc (*.glr)");

    if( !pathToSave.isEmpty())
    {
        activeGLR->setPathToSave( pathToSave );
        save_start();
    }

}

void Gameloc::writeWithTabs(int tabs, QString text)
{
    for(int i = 0; i < tabs; i++)
        infoFile->write("\t");
    infoFile->write( tr("%1\n").arg(text).toStdString().c_str());
}

QString Gameloc::getFileNameFromPath( QString path )
{
    QString result;

    for( int i = path.count()-1; i > 0; i--)
    {
        if( path.at(i) == QChar('/'))
            break;
        result.push_front(path.at(i));
    }

    return result;
}

QStringList Gameloc::getFileTree(QString dir)   // Получение дерева файлов
{
    QStringList result;
    QDir Dir(dir);

    QFileInfoList filelist = Dir.entryInfoList( QDir::Files );

    for( int i = 0; i < filelist.count(); i++)
    {
        if(( filelist.at(i).absoluteFilePath().toLower().right(3) == "wav" ) ||
           ( filelist.at(i).absoluteFilePath().toLower().right(3) == "mp3" ) ||
           ( filelist.at(i).absoluteFilePath().toLower().right(3) == "ogg" ))
            result << filelist.at(i).absoluteFilePath();    // Получаем пути файлов содержащихся в dir,
                                                            // если они нужного типа (аудиофайлы)
    }
    filelist = Dir.entryInfoList( QDir::NoDotAndDotDot | QDir::Dirs );

    for( int i = 0; i < filelist.count(); i++)
        result += getFileTree( filelist.at(i).absoluteFilePath());  // Переходим в дочерние папки


    return result;
}

QStringList Gameloc::getFolderTree(QString dir)    // Получение дерева папок
{
    QStringList result;
    QDir Dir(dir);

    QFileInfoList folderlist = Dir.entryInfoList( QDir::Dirs | QDir::NoDotAndDotDot );

    for( int i = 0; i < folderlist.count(); i++)
    {
        result << folderlist.at(i).absoluteFilePath();
        result += getFolderTree( folderlist.at(i).absoluteFilePath() );
    }

    return result;
}

void Gameloc::clearRevoiceTable()
{
    ui->revoicesTable->setRowCount(0);

    setPlayerAvailable(false);
}

void Gameloc::setPlayerAvailable(bool available)
{
    ui->playerGroup    ->setEnabled(available);
    ui->addSoundButton ->setEnabled(available);
    ui->recordNewButton->setEnabled(available);
}

void Gameloc::cnf_start()
{
    cnf_fileTree  = new QStringList;
    cnf_path2orig = new QString( newFileDialog->getPathToOriginal() );
    cnf_path2temp = new QString( gameloc_tempFolders_path + "/" + newFileDialog->getName());
    cnf_treeIndex = new int;

    *cnf_treeIndex = 0;

    progressDialog = new ProgressDialog(this);

    QString     *tempString   = new QString;
    QStringList *tempFileTree = new QStringList( getFileTree( *cnf_path2orig ));

    for( int i = 0; i < tempFileTree->count(); i++)  // Получение дерева файлов без путей.
    {
        *tempString = tempFileTree->at(i);
        *cnf_fileTree << tempString->remove( *cnf_path2orig );
    }

    // Получение имени папки указанной в newFileDialog
    tempString->clear();

    for( int i = cnf_path2orig->count() - 1; i > 0 ; i--)
    {
        tempString->push_front(cnf_path2orig->at(i));

        if( cnf_path2orig->at(i) == QChar('/'))
            break;
    }

    cnf_path2copySounds = new QString( *cnf_path2temp + "/" + *tempString);

    // Освобождение памяти от временных объектов и начало копирования
    delete tempFileTree;
    delete tempString;

    if( t == NULL )
        t = new QTimer;
    t->start(1);

    connect( t, SIGNAL(timeout()), SLOT(cnf_createFolders()));

    progressDialog->setTitle("Создание нового проекта");
    progressDialog->setMaxProgress( cnf_fileTree->count());
    progressDialog->setMaxFullProgress( cnf_fileTree->count() * 3);
    progressDialog->show();
}

void Gameloc::cnf_createFolders()
{
    QDir *tempDir = new QDir;

    tempDir->mkpath( *cnf_path2copySounds + cnf_fileTree->at(*cnf_treeIndex));  // Создание папки

    *cnf_treeIndex += 1;   // При следующем вызове будет создаватся папка с именем следующего файла в cnf_fileTree

    // Отображение на saveDialog прогресса
    progressDialog->setText( tr("Создание папок: %1 из %2").arg( *cnf_treeIndex )
                                                         .arg( cnf_fileTree->count()));
    progressDialog->incrementProgress();
    progressDialog->incrementFullProgress();

    delete tempDir;

    if( *cnf_treeIndex == cnf_fileTree->count())                     // Если все нужные папки созданы..
    {
        disconnect(t, SIGNAL(timeout()), this, SLOT(cnf_createFolders())); // .. прекратить копирование

        *cnf_treeIndex = 0;
        progressDialog->setProgress(0);                                // .. обнулить прогресс в progressDialog

        connect( t, SIGNAL(timeout()), SLOT(cnf_copyFiles()));       // .. и начать копирование файлов
    }
}

void Gameloc::cnf_copyFiles()
{
    // Обновление progressDialog
    progressDialog->setText( tr("Копирование файлов: %1 из %2").arg( *cnf_treeIndex )
                                                             .arg( cnf_fileTree->count()));

    // Копирование
    if( QFile::exists( *cnf_path2copySounds + cnf_fileTree->at( *cnf_treeIndex ) + "/original." + cnf_fileTree->at( *cnf_treeIndex ).right(3) ))
        QFile::remove( *cnf_path2copySounds + cnf_fileTree->at( *cnf_treeIndex ) + "/original." + cnf_fileTree->at( *cnf_treeIndex ).right(3));

    if( !QFile::copy( *cnf_path2orig + cnf_fileTree->at( *cnf_treeIndex ),
                      *cnf_path2copySounds + cnf_fileTree->at( *cnf_treeIndex ) + "/original." + cnf_fileTree->at( *cnf_treeIndex ).right(3)))
        QMessageBox::critical(this, "Ошибка копирования", tr("Не удалось скопировать файл %1 в %2")
                                                         .arg( *cnf_path2orig + cnf_fileTree->at( *cnf_treeIndex ) )
                                                         .arg( *cnf_path2copySounds + cnf_fileTree->at( *cnf_treeIndex ) + "/original." + cnf_fileTree->at( *cnf_treeIndex ).right(3)));

    // Инкримент индекса и проверка на завершение
    *cnf_treeIndex += 1;
    progressDialog->incrementProgress();
    progressDialog->incrementFullProgress();

    if( *cnf_treeIndex == cnf_fileTree->count())
    {
        disconnect( t, SIGNAL(timeout()), this, SLOT(cnf_copyFiles()));

        progressDialog->setText("Генерация info.dat");
        progressDialog->setProgress(0);

        infoFile = new QFile( *cnf_path2temp + "/info.dat");
        infoFile->open( QFile::WriteOnly);

        cnf_mainInfoWriten = false;

        cnf_curPath = new QStringList;
        cnf_prevPath = new QStringList;

        *cnf_treeIndex = 0;
        cnf_tabs = 0;
        connect( t, SIGNAL(timeout()), SLOT(cnf_generateInfo()));   // И начинаем генерировать info.dat
    }
}

void Gameloc::cnf_generateInfo()
{
    // Запись основной информации
    if( !cnf_mainInfoWriten )
    {
        writeWithTabs(cnf_tabs, tr("version %1")        .arg(version));
        writeWithTabs(cnf_tabs, tr("projectName %1")    .arg(newFileDialog->getName()));
        writeWithTabs(cnf_tabs, tr("hasIcon %1")        .arg(newFileDialog->hasIcon()));
        writeWithTabs(cnf_tabs, tr("maxDifference %1")  .arg(newFileDialog->getMaxDiff()));
        writeWithTabs(cnf_tabs, tr("totalFiles %1")     .arg(cnf_fileTree->count()));
        writeWithTabs(cnf_tabs,    "translated 0");
        writeWithTabs(0, " ");

        cnf_mainInfoWriten = true;
    }
    // Запись дерева файлов

        // Получить новый текущий путь
    if( cnf_fileTree->at(*cnf_treeIndex).right(3).toLower() == "wav" ||
        cnf_fileTree->at(*cnf_treeIndex).right(3).toLower() == "mp3" ||
        cnf_fileTree->at(*cnf_treeIndex).right(3).toLower() == "ogg")    // Если файл звуковой
    {
        *cnf_curPath = getFileParentDirs( getFileParentDirs(*cnf_path2copySounds + "/sdaf").last() + cnf_fileTree->at(*cnf_treeIndex));

        // Если первая итерация цикла
        if( *cnf_treeIndex == 0)
        {
            // Записать инфу о папках
            for( int j = 0; j < cnf_curPath->count(); j++)
            {
                cnf_tabs++;
                cnf_generateInfo_writeFolder( cnf_curPath->at(j));
            }
        }
        else
        {
            // Если путь к файлу отличается от предыдущего
            if( *cnf_curPath != *cnf_prevPath)
            {
                // Если путь к текущему больше чем к предыдущему
                if( cnf_curPath->count() > cnf_prevPath->count())
                {
                    for( int j = cnf_prevPath->count() - 1; j > 0; j--)  // Выясняем, является ли текущая папка подпапкой предыдущей
                        if( cnf_prevPath->at(j) != cnf_curPath->at(j))
                        {
                            cnf_isSubDir = false;
                            writeWithTabs(cnf_tabs, "[end]" );
                            cnf_tabs--;
                            writeWithTabs(0, " ");
                        }
                    if( cnf_isSubDir ) // Если папка является подпапкой предыдущей
                    {
                        // Дописать информацию о родительских папках
                        for( int j = cnf_prevPath->count(); j < cnf_curPath->count(); j++)
                        {
                            cnf_tabs++;
                            cnf_generateInfo_writeFolder( cnf_curPath->at(j) );
                        }
                    }
                    else
                    {
                        // Выясняем, с какого места надо начинать писать инфу
                        int j = 0;
                        for( j ; j < cnf_prevPath->count(); j++)
                            if( cnf_prevPath->at(j) != cnf_curPath->at(j))
                                break;

                        // Пишем информацию о родительских папках текущего файла
                        for( j ; j < cnf_curPath->count(); j++ )
                        {
                            cnf_tabs++;
                            cnf_generateInfo_writeFolder( cnf_curPath->at(j));
                        }
                    }
                    cnf_isSubDir = true;
                }
                // Если путь меньше чем предыдущий (произошел выход и подпапки или переход в другую)
                if( cnf_curPath->count() < cnf_prevPath->count())
                {
                    // Закрыть j папок ( Где j - кол-во папок предыдущей - текущей )
                    for( int j = cnf_prevPath->count() - cnf_curPath->count(); j > 0; j--)
                    {
                        writeWithTabs(cnf_tabs, "[end]");
                        writeWithTabs(0, " ");
                        cnf_tabs--;
                    }
                    // Если переход не в родительскую папку, а в другую, то проверить какие папки отличаются и закрыть их
                    for( int j = cnf_curPath->count() - 1; j > 0; j--)
                    {
                        if( cnf_curPath->at(j) != cnf_prevPath->at(j))
                        {
                            writeWithTabs(cnf_tabs, "[end]" );
                            writeWithTabs(0, " ");
                            cnf_tabs--;
                        }
                    }

                    // Записать информацию о текущей папке и её родителях
                    for( int j = 0; j < cnf_curPath->count(); j++)
                    {
                        if( cnf_curPath->at(j) != cnf_prevPath->at(j))    // Выясняем с какого места начинается отличие, и оттуда записываем инфу
                        {
                            for( j; j < cnf_curPath->count(); j++)   // Предотвращение возможного бага, если в отличающихся путях возникнет равенство имен подпапок
                            {
                                cnf_tabs++;
                                cnf_generateInfo_writeFolder( cnf_curPath->at(j));
                            }
                            break;
                        }
                    }
                }

                // Если пути отличаются, но количеством родителей равны
                if( cnf_curPath->count() == cnf_prevPath->count())
                {
                    // Закрыть отличающиеся родительские папки
                    for( int j = 0; j < cnf_curPath->count(); j++)
                    {
                        if( cnf_curPath->at(j) != cnf_prevPath->at(j))
                        {
                            for( j; j < cnf_curPath->count(); j++) // Предотвращение возможного бага, если в отличающихся путях возникнет равенство имен подпапок
                            {
                                writeWithTabs(cnf_tabs, "[end] " + cnf_prevPath->at(j));
                                writeWithTabs(0, " ");
                                cnf_tabs--;
                            }
                            break;
                        }
                    }

                    // Записать информацию о текущей папке и её родителях
                    for( int j = 0; j < cnf_curPath->count(); j++)
                    {
                        if( cnf_curPath->at(j) != cnf_prevPath->at(j))    // Выясняем с какого места начинается отличие, и оттуда записываем инфу
                        {
                            for( j; j < cnf_curPath->count(); j++)   // Предотвращение возможного бага, если в отличающихся путях возникнет равенство имен подпапок
                            {
                                cnf_tabs++;
                                cnf_generateInfo_writeFolder( cnf_curPath->at(j));
                            }
                            break;
                        }
                    }
                }
            }
        }

        cnf_generateInfo_writeFile(*cnf_treeIndex); // После того как с папками разобрались, пишем инфу о файле
        *cnf_prevPath = *cnf_curPath;
    }

    *cnf_treeIndex += 1;

    progressDialog->incrementProgress();
    progressDialog->incrementFullProgress();

    if( *cnf_treeIndex == cnf_fileTree->count())
    {
        for( cnf_tabs; cnf_tabs >= 0; cnf_tabs--)
            writeWithTabs(cnf_tabs, "[end]");   // закрываем оставшиеся папки

        disconnect( t, SIGNAL(timeout()), this, SLOT(cnf_generateInfo()));
        cnf_end();
    }

}

void Gameloc::cnf_generateInfo_writeFolder(QString name)
{
    writeWithTabs(cnf_tabs, "[Folder]");
    writeWithTabs(cnf_tabs, "name " + name);
    writeWithTabs(cnf_tabs, "iconStyle 0");
    writeWithTabs(0, " ");
}

void Gameloc::cnf_generateInfo_writeFile( int index)
{
    QString *fileName = new QString;

    // Получение имени файла
    for( int i = cnf_fileTree->at(index).count() - 1; i > 0; i--)
    {
        if( cnf_fileTree->at(index).at(i) == QChar('/'))
            break;

        fileName->push_front( cnf_fileTree->at(index).at(i) );
    }

    writeWithTabs(cnf_tabs+1, "[Sound]");
    writeWithTabs(cnf_tabs+1, "fileName " + *fileName);
    writeWithTabs(cnf_tabs+1, "editFinished 0");
    writeWithTabs(cnf_tabs+1, tr("length %1").arg( playerAndRecorder->getLengthOfFile( *cnf_path2orig + cnf_fileTree->at(index) )));
    writeWithTabs(cnf_tabs+1, "[end]");
    writeWithTabs(0, "");

    delete fileName;
}

void Gameloc::cnf_end()
{    
    if( newFileDialog->hasIcon() )
    {
        if( QFile::exists(*cnf_path2temp + "/icon." + newFileDialog->getPathToIcon().right(3)))
            QFile::remove(*cnf_path2temp + "/icon." + newFileDialog->getPathToIcon().right(3));

        if( !infoFile->copy( newFileDialog->getPathToIcon(),
                             *cnf_path2temp + "/icon." + newFileDialog->getPathToIcon().right(3)))
        {
            QString errorText;

            switch( infoFile->error())
            {
            case 0:
                errorText = "No Error Occured"; break;
            case 1:
                errorText = "An error occurred when reading from the file."; break;
            case 2:
                errorText = "An error occurred when writing to the file."; break;
            case 3:
                errorText = "A fatal error occurred."; break;
            case 4:
                errorText = "Out of resources (e.g., too many open files, out of memory, etc.)"; break;
            case 5:
                errorText = "The file could not be opened."; break;
            case 6:
                errorText = "The operation was aborted."; break;
            case 7:
                errorText = "A timeout occurred."; break;
            case 8:
                errorText = "An unspecified error occurred."; break;
            case 9:
                errorText = "The file could not be removed."; break;
            case 10:
                errorText = "The file could not be renamed."; break;
            case 11:
                errorText = "The position in the file could not be changed."; break;
            case 12:
                errorText = "The file could not be resized."; break;
            case 13:
                errorText = "No permissions"; break;
            case 14:
                errorText = "The file could not be copied."; break;
            }

            QMessageBox::critical(this, "Ошибка создания GLR!", tr("Не удалось скопировать иконку из %1\nв %2\nТекст Ошибки: %3")
                                                                .arg(newFileDialog->getPathToIcon())
                                                                .arg(*cnf_path2temp)
                                                                .arg(errorText));
        }
    }

    infoFile->close();

    progressDialog->setText("Открытие сгенерированного GLR");

    delete newFileDialog;

    delete cnf_fileTree;
    delete cnf_path2copySounds;
    delete cnf_path2orig;
    delete cnf_treeIndex;

    openFromTempPath( *cnf_path2temp, false );

    delete cnf_path2temp;
}

QStringList Gameloc::getFileParentDirs(QString path)
{
    QString *tempString = new QString;
    QStringList result;

    if( path[0] == '/')
        path = path.remove(0,1);

    for( int i = 0; i < path.count(); i++)
    {
        if( path[i] != '/')
            tempString->push_back(path[i]); // Получение имени папки
        else
        {
            result << *tempString;  // Добавление имени папки в результат
            tempString->clear();
        }
    }

    delete tempString;

    return result;
}

void Gameloc::save_start()
{
    progressDialog = new ProgressDialog(this);
    progressDialog->setText("Генерация info.dat");
    progressDialog->setTitle("Сохранение " + getFileNameFromPath(activeGLR->getPathToSave()));
    progressDialog->hideProgress();
    progressDialog->hideFullProgress();

    // Подключаем функцию генерации к таймеру
    progressDialog->show();
    t->start(1);
    connect( t, SIGNAL(timeout()), SLOT(save_generateInfo()));
}

void Gameloc::save_generateInfo()
{
    // Генерация info.dat
    qDebug() << "Gameloc::save_generateInfo: Генерация info.dat";

    QFile::remove(activeGLR->getTempPath() + "/info.dat");

    infoFile = new QFile( activeGLR->getTempPath() + "/info.dat");
    if( infoFile->open(QIODevice::WriteOnly))               // Создание файла info.dat
    {
        qDebug() << "Gameloc::save_generateInfo: info.dat создан. Начинаю наполнение";

        // Наполнение основной информацией о
        writeWithTabs(0, "version " + version);

        infoFile->write( tr("projectName %1\n")               .arg( activeGLR->getProjectName() )                .toStdString().c_str());
        infoFile->write( tr("hasIcon %1\n")                .arg( activeGLR->hasIcon())                     .toStdString().c_str());
        infoFile->write( tr("maxDifference %1\n")          .arg( activeGLR->getMaxDifference())            .toStdString().c_str());
        infoFile->write( tr("totalFiles %1\n")             .arg( activeGLR->getTotalFiles())               .toStdString().c_str());
        infoFile->write( tr("translated %1\n")             .arg( activeGLR->getTranslated())            .toStdString().c_str());
        infoFile->write( tr("\n").toStdString().c_str());

        qDebug() << "Gameloc::save_generateInfo: Основная информация записана. Начинаю записывать информацию о файлах и папках";

        save_generateInfo_writeFolders(1, activeGLR->getTree());
        writeWithTabs(0, "[end]");

        qDebug() << "Gameloc::save_generateInfo: info.dat создан. Данные скопированы";

        infoFile->close();

        arc_start();
    }
    else
        QMessageBox::critical(this, "Ошибка сохранения файла", tr("Ошибка сохранения файла %1. Невозможно создать или открыть.").arg(infoFile->fileName()));


    disconnect( t, SIGNAL(timeout()), this, SLOT(save_generateInfo()));
}


void Gameloc::save_generateInfo_writeFolders ( int tabs, Folder* curFolder )
{
        qDebug() << "Gameloc::save_generateInfo_writeFolders: Сохраняется инфа из папки " << curFolder->getPath();

        // Запись информации о папке
        writeWithTabs( tabs, "[Folder]");
        writeWithTabs( tabs, "name "       + curFolder->getName());

        if( !curFolder->getCommentary().isEmpty())
            writeWithTabs( tabs, "commentary " + curFolder->getCommentary());

        writeWithTabs( tabs, tr("iconStyle %1").arg(curFolder->getIconStyle()));

        writeWithTabs(0, tr("\n")); // Добавление пропусков строк для читабельности info файла

        qDebug() << "Gameloc::save_generateInfo_writeFolders: Основная информация сохранена, ищу папки в этой папке...";

        if( curFolder->getFoldersCount() != 0) // Проверка наличия других папок в текущей
        {
            qDebug() << "Gameloc::save_generateInfo_writeFolders: ...обнаружены. Функция вызывает сама себя с новыми параметрами";

            for( int i = 0; i < curFolder->getFoldersCount(); i++)
                save_generateInfo_writeFolders(tabs+1, curFolder->getFolders().at(i));
        }
        else
            qDebug() << "Gameloc::save_generateInfo_writeFolders: Папок больше нет. Записываю инфу о файлах";

        for(int i = 0; i < curFolder->getTags().count(); i++)
            writeWithTabs( tabs, tr("tag %1").arg( curFolder->getTags().at(i)) );

        // Заполнение инфой о файлах
        SoundFile *tempSound;
        Revoice *tempRevoice;
        for( int i = 0; i < curFolder->getFilesCount(); i++)
        {
            tempSound = curFolder->getFiles().at(i);

            writeWithTabs(tabs+1, "[Sound]");
            writeWithTabs(tabs+1, "fileName " +  tempSound->getName());
            writeWithTabs(tabs+1, "editFinished " + tr("%1").arg(tempSound->editIsFinished()));
            writeWithTabs(tabs+1, "length " + playerAndRecorder->getLengthOfFile( tempSound->getPathToOrig()));

            if( ! tempSound->getCommentary().isEmpty() )
                writeWithTabs( tabs+1, "commentary " + tempSound->getCommentary());

            for( int j = 0; j < tempSound->getTags().count(); j++)  // Теги
                writeWithTabs(tabs+1, "tag " + tempSound->getTags().at(j));

            if( !tempSound->getTranslateText().isEmpty())    // Перевод текстом (TODO: Преобразование символа \n в \\n при сохранении)
                writeWithTabs( tabs+1, "textTranslate " + tempSound->getTranslateText());

            // Переозвучки
            for( int j = 0; j < tempSound->getRevoices().count(); j++)
            {
                tempRevoice = tempSound->getRevoice(j);

                writeWithTabs(0, tr("\n"));
                writeWithTabs(tabs+2, "[Revoice]");
                writeWithTabs(tabs+2, "fileName " + tempRevoice->getFilename());
                writeWithTabs(tabs+2, "general " + tr("%1").arg(tempRevoice->isGeneral()));
                writeWithTabs(tabs+2, "length " + playerAndRecorder->getLengthOfFile( tempRevoice->getPath()));

                if( ! tempRevoice->getName().isEmpty())
                    writeWithTabs(tabs+2, "name " + tempRevoice->getName());

                if( ! tempRevoice->getAuthor().isEmpty() )
                    writeWithTabs( tabs+2, "author " + tempRevoice->getAuthor());

                writeWithTabs(tabs+2, "[end]");
            }
            writeWithTabs(tabs+1, "[end]");
            writeWithTabs(0, tr("\n"));
        }
        writeWithTabs(tabs, "[end]");

        qDebug() << "Gameloc::save_generateInfo_writeFolders: Заполнение информацией окончено";
}

void Gameloc::setActiveSound(QTreeWidgetItem *n_activeSound)
{
    activeSound = (SoundFile*) n_activeSound; setPlayerAvailable(true);
}

void Gameloc::arc_start()
{
    qDebug() << "Gameloc::arc_start: Начало архивации";

    arc_path = new QString( activeGLR->getPathToSave());

    if( QFile::exists(*arc_path) )
        QFile::remove(*arc_path);

    qDebug() << "Gameloc::arc_start: Путь сохранения glr: " << *arc_path;
    qDebug() << "Gameloc::arc_start: Путь ко временной папке: " << activeGLR->getTempPath();

    progressDialog->showProgress();
    progressDialog->setProgress(0);
    progressDialog->setMaxProgress(100);
    progressDialog->setText( tr("Архивация"));

    arc_7zr = new QProcess();

    connect( t, SIGNAL(timeout()), SLOT(arc_archivating()));
}

void Gameloc::arc_archivating()
{
    QString *arcDir = new QString;
    QString *cutedPath = new QString;
    QStringList *tempPath = new QStringList( getFileParentDirs( *cutedPath ));

    QString *arg = new QString();
    *arg = "create -r -dip \"" + *arc_path + "\" ./";

    // qDebug() << "Gameloc::arc_archivating: Запуск Arc с параметрами: " << *arg;

    arc_7zr->start("arc " + *arg);

    if( !arc_7zr->waitForStarted())
        QMessageBox::critical(this, "Ошибка", "Не удалось запустить FreeArc.");

    delete arg;
    delete arcDir;
    delete cutedPath;
    delete tempPath;

    disconnect( t, SIGNAL(timeout()), this, SLOT(arc_archivating()));
    connect( t, SIGNAL(timeout()), this, SLOT(updateProgressWhileArchivating()));
}

void Gameloc::updateProgressWhileArchivating()
{
    QString printedData;
    int progress = 0;

    if( ! progressDialog->progressVisible() )
        progressDialog->showProgress();

    if( arc_7zr->state() == QProcess::NotRunning )
    {
        progressDialog->close();
        delete progressDialog;

        activeGLR->glrIsSaved();

        disconnect( t, SIGNAL(timeout()), this, SLOT(updateProgressWhileArchivating()));
        delete arc_7zr;
    }
    else
    {
        printedData = arc_7zr->readLine();

        if( printedData.contains("ERROR:"))
        {
            QMessageBox::critical(this, "Ошибка FreeArc", tr("Во время архивации произошла ошибка: %1").arg(printedData));
        }

        printedData = printedData.remove("\010").remove("%");
        printedData = printedData.trimmed();

        if( !printedData.isEmpty())
        {
            progress = (int) printedData.right(5).toFloat();
            qDebug() << printedData << " | " << progress;
            progressDialog->setProgress(progress);
        }
    }
}

void Gameloc::updateRevoicesTable_on_currentSoundChanged(QTreeWidgetItem *newItem)
{
    // BUG: Изменения основной переозвучки не всегда сохраняются
    SoundFile *tempSound = (SoundFile*) newItem;

    if( tempSound->getType() == "SoundFile")
    {
        disconnect( ui->translateField, SIGNAL(textChanged()),        this, SLOT(on_translateTextChanged()));
        disconnect( ui->revoicesTable,   SIGNAL(cellChanged(int,int)), this, SLOT(cellEdited(int, int)));

        activeSound = tempSound;
        tempSound->showRevoicesInTable(newItem);

        ui->translateField->setPlainText( activeSound->getTranslateText() );

        connect( ui->translateField, SIGNAL(textChanged()), this, SLOT(on_translateTextChanged()));
        connect( ui->revoicesTable, SIGNAL(cellChanged(int,int)), SLOT(cellEdited(int, int)));

         ui->revoicesTable->setCurrentCell(0,0);

        setPlayerAvailable(true);
    }
}

void Gameloc::on_translateTextChanged()
{
    activeSound->setTranslateText( ui->translateField->toPlainText());
    activeGLR->glrIsChanged();
}

void Gameloc::addRevoiceFromFolder()
{
    qDebug() << "Gameloc::addRevoiceFromFolder: Вызвана функция для добавления вариантов озвучки с компьютера";
    QStringList files = QFileDialog::getOpenFileNames(this, "Выберите варианты переозвучки для файла " + getFileNameFromPath(activeSound->getName()),
                                                      pathToLastAddedRevoice, "Аудиофайлы (*.mp3 *.wav *.ogg)");

    QDir *d = new QDir;
    if( !files.isEmpty())
    {
        QString *tempStr = new QString(files.at(0));
        pathToLastAddedRevoice = tempStr->remove(getFileNameFromPath(*tempStr));
        delete tempStr;

        qDebug() << "Gameloc::addRevoiceFromFolder: Создаю папку " << activeSound->getPath() + "/revoices/";
        d->mkpath(activeSound->getPath() + "/revoices/");

        for( int i = 0; i < files.count(); i++)
        {

            if( files.at(i).right(3) != activeSound->getPath().right(3))
            {
                qDebug() << "Gameloc::addRevoiceFromFolder: " <<  files.at(i).right(3) << " != " << activeSound->getPath().right(3);
                qDebug() << "Gameloc::addRevoiceFromFolder: Конвертирование файла";
                playerAndRecorder->convertFile(files.at(i), tr("%1/revoices/var%2.%3")
                                                .arg(activeSound->getPath())
                                                .arg(activeSound->getRevoicesCount())
                                                .arg( activeSound->getName().right(3)));
            }
            else
            {
                qDebug() << "Gameloc::addRevoiceFromFolder: Копирование файла из " << files.at(i) << " в";
                qDebug() << "Gameloc::addRevoiceFromFolder: " << tr("%1/revoices/var%2.%3")
                                                                    .arg(activeSound->getPath() )
                                                                    .arg(activeSound->getRevoicesCount())
                                                                    .arg( activeSound->getName().right(3));

                QFile::copy(files.at(i), tr("%1/revoices/var%2.%3").arg(activeSound->getPath())
                                                                   .arg(activeSound->getRevoicesCount())
                                                                   .arg( activeSound->getName().right(3)));
            }

            activeSound->addRevoice(userName, playerAndRecorder->getLengthOfFile(tr("%1/revoices/var%2.%3")
                                                                   .arg(activeSound->getPath())
                                                                   .arg(activeSound->getRevoicesCount())
                                                                   .arg( activeSound->getName().right(3))));

            ui->revoicesTable->clear();
            activeSound->showRevoicesInTable( (QTreeWidgetItem*) activeSound);

            activeGLR->glrIsChanged();
        }
    }
    else
        qDebug() << "Gameloc::addRevoiceFromFolder: Ни одного файла выбрано небыло";

    delete d;
}

void Gameloc::deleteRevoice()
{
    int row = ui->revoicesTable->currentRow();
    activeSound->deleteRevoice( row - 1 );

    activeSound->showRevoicesInTable( (QTreeWidgetItem*) activeSound );
    activeGLR->glrIsChanged();
}

void Gameloc::recordNewRevoice( bool start)
{
    QString file = tr("%1/var%2.%3").arg( activeSound->getPath() + "/revoices")
                                .arg( activeSound->getRevoicesCount() )
                                .arg( activeSound->getName().right(3));

    if( start)
    {
        QDir *d = new QDir;
        d->mkpath(activeSound->getPath() + "/revoices");
        delete d;

        qDebug() << "Gameloc::recordNewRevoice: Начинаю запись файла " << file;
        playerAndRecorder->closeFile();

        if( ! playerAndRecorder->startRecord(file))
        {
            disconnect( ui->recordNewButton, SIGNAL(toggled(bool)), this, SLOT(recordNewRevoice(bool)));
            ui->rerecordButton->setChecked(false);
            connect( ui->recordNewButton, SIGNAL(toggled(bool)), this, SLOT(recordNewRevoice(bool)));
        }
    }
    else
    {
        playerAndRecorder->stopRecord();

        activeSound->addRevoice( userName, playerAndRecorder->getLengthOfFile(file));
        activeSound->showRevoicesInTable((QTreeWidgetItem*) activeSound);

        activeGLR->glrIsChanged();
    }
}

void Gameloc::rerecordRevoice(bool start)
{
    qDebug() << "Gameloc::rerecordRevoice: Вызвана функция перезаписи переозвучки";
    int index = ui->revoicesTable->currentRow()-1;

    if( start)
    {
        playerAndRecorder->closeFile();
        qDebug() << "Gameloc::rerecordRevoice: Кнопка нажата, начинаю запись";
        ui->revoicesTable->setEnabled(false);

        qDebug() << "Gameloc::rerecordRevoice: Запись будет происходить в " << activeSound->getRevoice(index)->getPath();
        QFile::remove(activeSound->getRevoice(index)->getPath());

        if( ! playerAndRecorder->startRecord( activeSound->getRevoice(index)->getPath() ))
        {
            disconnect( ui->rerecordButton, SIGNAL(toggled(bool)), this, SLOT(rerecordRevoice(bool)));
            ui->rerecordButton->setChecked(false);
            connect( ui->rerecordButton, SIGNAL(toggled(bool)), this, SLOT(rerecordRevoice(bool)));
        }
    }
    else
    {
        qDebug() << "Gameloc::rerecordRevoice: Кнопка отжата, заканчиваю запись";
        playerAndRecorder->stopRecord();
        ui->revoicesTable->setEnabled(true);

        activeSound->getRevoice( index)->setLength( playerAndRecorder->getLengthOfFile( activeSound->getRevoice(index)->getPath()));
        activeSound->pToOriginal->getRevoice( index)->setLength( playerAndRecorder->getLengthOfFile( activeSound->getRevoice(index)->getPath()));

        activeSound->showRevoicesInTable((QTreeWidgetItem*) activeSound);
        activeGLR->glrIsChanged();
    }
}

void Gameloc::reopenRevoice()
{
    loadRevoiceOnSelect( ui->revoicesTable->currentRow());
}

void Gameloc::on_addButton_clicked()
{
    addButtonDialog = new AddButtonDialog(this);
    addButtonDialog->show();
}

void Gameloc::writeSettings()
{
    settings->setValue("geometry", saveGeometry());
    settings->setValue("recentFiles", recentFiles);
}

void Gameloc::readSettings()
{
    settings = new QSettings("Cydeamon's Projects", "Gameloc");

    restoreGeometry(settings->value("geometry").toByteArray());
    recentFiles = settings->value("recentFiles").toStringList();
    updateRecentFileActions();
}

void Gameloc::updateRecentFileActions()
{
    QList <QAction *> actions = ui->openMenu->actions();

    for( int i = 2; i < actions.count(); i++)
    {
        disconnect( actions.at(i), SIGNAL(triggered()), this, SLOT(openRecentFile()));
        actions.at(i)->setVisible(false);
    }

    for( int i = 0; i < 10 && i < recentFiles.count(); i++)
    {
        QAction *tempAction = ui->openMenu->addAction( tr("%1: %2").arg(i+1).arg(getFileNameFromPath(recentFiles.at(i))));
        tempAction->setIcon( QIcon(":/icons/glr_icon.png"));
        tempAction->setData(recentFiles.at(i));

        connect( tempAction, SIGNAL(triggered()), SLOT(openRecentFile()));
    }

    if( recentFiles.count() > 0)
    {
        ui->openMenu->addSeparator();
        QAction *clearRecentFiles = ui->openMenu->addAction("Очистить список");

        connect( clearRecentFiles, SIGNAL(triggered()), SLOT(clearRecentFileList()));
    }
}

void Gameloc::clearRecentFileList()
{
    recentFiles.clear();
    writeSettings();
    updateRecentFileActions();
}

void Gameloc::openRecentFile()
{
    QAction *action = qobject_cast<QAction *>(sender());
    if( action)
    {
        if( QFile::exists( action->data().toString() ))
        {
            progressDialog = new ProgressDialog(this);
            progressDialog->show();
            progressDialog->hideFullProgress();
            progressDialog->hideProgress();
            progressDialog->setText("Распаковка и открытие файла");
            progressDialog->setTitle(tr("Открытие %1").arg(getFileNameFromPath(action->data().toString())));

            archiveToExtract = new QString( action->data().toString());
            connect( t, SIGNAL(timeout()), SLOT(extractArchiveOnOpen()));
        }
        else
        {
            // Если файла не существует
            QMessageBox::critical(this, "Файла не существует", "Данного файла проекта не существует\nПохоже что он был удален или перемещен");

            // Удаляем его из списка последних открытых
            for( int i = 0; i < recentFiles.count(); i++)
                if( action->data().toString() == recentFiles[i])
                    recentFiles.removeAt(i);

            // И обновляем меню
            updateRecentFileActions();
        }
    }
}

void Gameloc::closeEvent(QCloseEvent *event)
{
    for( int i = 0; i < openedFiles.count(); i++)
    {
        if( openedFiles[i]->changed())
            unsavedFiles.push_back( openedFiles[i]);
    }

    event->ignore();

    close_index = -1;
    close_allSaved = false;
    close_yesToAll = false;
    close_noToAll  = false;

    connect(this, SIGNAL(saved()), SLOT(onClose()));

    onClose();
}

void Gameloc::onClose()
{
    close_index++;

    if( close_index != unsavedFiles.count())    // Если сохранены не все файлы
    {
        if( close_yesToAll == close_noToAll)    // Если небыло нажато "Да для всех" или "Нет для всех"
        {
            int answer = QMessageBox::question(this, "Проект был изменен", tr("Проект %1 был изменен, но не сохранен\nЖелаете сохранить изменения?").arg(unsavedFiles.at(close_index)->getProjectName()),
                                               QMessageBox::Yes| QMessageBox::YesToAll | QMessageBox::No | QMessageBox::NoToAll | QMessageBox::Cancel);

            if( answer == QMessageBox::Yes)
            {
                activeGLR = unsavedFiles.at(close_index);
                on_saveAction_triggered();
            }
            if( answer == QMessageBox::YesToAll)
            {
                close_yesToAll = true;
                activeGLR = unsavedFiles.at(close_index);
                on_saveAction_triggered();
            }
            if( answer == QMessageBox::No)
                emit saved();               // После выхода из функции она будет вызвана вновь, но уже с новым индексом

            if( answer == QMessageBox::NoToAll)
            {                
                settings->setValue("tags", QStringList());
                writeSettings();    // Если пользователь выбрал "Нет для всех", то просто выходим из программы
                exit(0);
            }

            if( answer == QMessageBox::Cancel)
            {
                close_allSaved = false;
                close_index = 0;
                close_noToAll = false;
                close_yesToAll = false;
                unsavedFiles.clear();

                disconnect(this, SIGNAL(saved()), this, SLOT(onClose()));
            }
        }

        if( close_yesToAll ) // Если было нажато "Да, для всех"
        {
            activeGLR = unsavedFiles.at(close_index);
            on_saveAction_triggered();
        }
    }
    else    // Если сохранены все файлы
    {
        // Очищаем временную папку
        hide();

        QDir d;
        d.setPath(gameloc_tempFolders_path);
        d.removeRecursively();

        // Сохраняем настройки и выходим
        settings->setValue("tags", QStringList());
        writeSettings();
        exit(0);
    }
}

void Gameloc::cellEdited(int row, int column)
{
    if( row == 0)   // Предотвращение изменения строки для оригинального файла
    {
        switch(column)
        {
        case 0:
            ui->revoicesTable->item(row, column)->setText("Оригинальный файл");
            break;
        case 1:
            ui->revoicesTable->item(row, column)->setText("");
            break;
        case 2:
            ui->revoicesTable->item(row, column)->setText( activeSound->getLength() );
        }
    }
    else    // Если редактируется переозвучка
    {
        switch(column)
        {
        case 0:
            activeSound->getRevoice(row-1)->setName( ui->revoicesTable->item(row, column)->text());
            activeGLR->glrIsChanged();
            break;
        case 1:
            activeSound->getRevoice(row-1)->setAuthor( ui->revoicesTable->item(row, column)->text());
            activeGLR->glrIsChanged();
            break;
        case 2:
            ui->revoicesTable->item(row, column)->setText( activeSound->getRevoice(row-1)->getLength() );
        }
    }
}

void Gameloc::editSoundProperties()
{
    editFilePropertiesDialog = new EditFileProperties_Dialog( (SoundFile*) ui->fileTree->currentItem(), this);
    editFilePropertiesDialog->show();

    activeGLR->glrIsChanged();
}

void Gameloc::on_editFolderProperties()
{
    editFolderPropsDialog = new editFolderProperties_dialog( (Folder*) ui->folderTree->currentItem(), this);
    editFolderPropsDialog->show();

    connect( editFolderPropsDialog, SIGNAL(saved(Folder*)), (Folder*) ui->folderTree->currentItem(), SLOT(updateFolderView()));
    connect( editFolderPropsDialog, SIGNAL(timeToClose()), SLOT(deleteEFP_dialog()));

    activeGLR->glrIsChanged();
}

void Gameloc::on_folderTree_currentItemChanged(QTreeWidgetItem *current)
{
    Folder* item = (Folder*) current;

    if( item->getType() == "GLR")
    {
        folderTree_showStatistic_action->setVisible(true);
        folderTree_closeActivePrj_action->setVisible(true);
        folderTree_clearAction->setVisible(false);
        folderTree_changeProperties_action->setVisible(false);
    }
    else
    {
        folderTree_showStatistic_action->setVisible(false);
        folderTree_closeActivePrj_action->setVisible(false);
        folderTree_clearAction->setVisible(true);
        folderTree_changeProperties_action->setVisible(true);

        fileTree_changeProperties_action->setEnabled( item->getFilesCount() );
        fileTree_clearAction->setEnabled( item->getFilesCount() );
    }
}

void Gameloc::clearFolder(bool revoices, bool texts)
{
    Folder* item = (Folder*) ui->folderTree->currentItem();

    for( int i = 0; i < item->getFilesCount(); i++)
    {
        if( texts && item->getFile(i)->hasTranslate())
        {
            item->getFile(i)->setTranslateText("");
            item->getFile(i)->setTextIconVisible(false);
        }
        if( revoices && item->getFile(i)->getRevoicesCount())
            for( int j = 0; j < item->getFile(i)->getRevoicesCount(); )
            {
                item->getFile(i)->deleteRevoice(j);
                item->getFile(i)->setRevoiceIconVisible(false);
            }
    }

    item->showFilesInTree( ui->folderTree->currentItem());
    activeGLR->glrIsChanged();
}

void Gameloc::clearSound_all()
{
    SoundFile* item = (SoundFile*) ui->fileTree->currentItem();

    for( int i = 0; i < item->getRevoicesCount(); )
        item->deleteRevoice(i);

    item->setRevoiceIconVisible(false);

    item->setTranslateText("");
    item->setTextIconVisible(false);

    item->showRevoicesInTable( ui->fileTree->currentItem());
    ui->translateField->setPlainText("");

    activeGLR->glrIsChanged();
}

void Gameloc::clearSound_text()
{
    SoundFile* item = (SoundFile*) ui->fileTree->currentItem();
    item->setTranslateText("");
    item->setTextIconVisible(false);

    ui->translateField->setPlainText("");
    activeGLR->glrIsChanged();
}

void Gameloc::clearSound_revoices()
{
    SoundFile* item = (SoundFile*) ui->fileTree->currentItem();

    for( int i = 0; i < item->getRevoicesCount();)
        item->deleteRevoice(i);

    item->setRevoiceIconVisible(false);
    item->showRevoicesInTable( ui->fileTree->currentItem());
    activeGLR->glrIsChanged();
}

void Gameloc::on_advancedSearchParamsAction_triggered()
{
    advancedSearchParamsDialog = new AdvancedSearchParamsDialog(this);
    advancedSearchParamsDialog->show();

    connect(advancedSearchParamsDialog, SIGNAL(readyToSearch(QString, QString, QStringList)),
                                        SLOT  (search_start   (QString, QString, QStringList)));
}

void Gameloc::search_fromMainWindow()
{
    search_start(searchField->text(), "", QStringList());
}

void Gameloc::search_start(QString partOfFilename, QString partOfCommentary, QStringList tags)
{
    search_partOfFilename       = partOfFilename;
    search_partOfCommentary     = partOfCommentary;
    search_tagList              = tags;
    search_curFolder            = activeGLR->getTree();
    search_somethingWasFounded  = false;
    search_fileIndex            = -1;

    search_subdirIndexes.push_back(0);

    connect( t, SIGNAL(timeout()), SLOT(search()));

    progressDialog = new ProgressDialog(this);
    progressDialog->show();

    progressDialog->setTitle("Поиск");
    progressDialog->hideFullProgress();
    progressDialog->hideProgress();
    progressDialog->setText("Поиск в папке " + activeGLR->getTree()->getName());

}

void Gameloc::search_continue()
{    
    progressDialog = new ProgressDialog(this);
    progressDialog->show();

    progressDialog->setTitle("Поиск");
    progressDialog->hideFullProgress();
    progressDialog->hideProgress();
    progressDialog->setText("Поиск в папке " + search_curFolder->getName());

    qDebug() << "Gameloc::search_continue: Продолжаю поиск";
    connect( t, SIGNAL(timeout()), SLOT(search()));
}

void Gameloc::search()
{
    progressDialog->setText("Поиск в папке " + search_curFolder->getName());

    SoundFile* searchResult = searchInCurFolder();

    if( searchResult )                                                                  // Если поиск удался
    {
        qDebug() << "Gameloc::search: Поиск удался. Осуществляется переход к папке и обновление действия для кнопки поиска";
        disconnect( t, SIGNAL(timeout()), this, SLOT(search()));

        searchAction->setIcon(QIcon(":/icons/continueSearch.png"));                     // Кнопка поиска теперь работает как "Искать далее"
        searchAction->setToolTip("Продолжить поиск");

        disconnect( searchAction, SIGNAL(triggered()), this, SLOT(search_continue()));
        disconnect( searchAction, SIGNAL(triggered()), this, SLOT(search_fromMainWindow()));

        connect( searchAction, SIGNAL(triggered()), SLOT(search_continue()));

        searchNext_mode = true;

        ui->folderTree->setCurrentItem( search_curFolder);
        search_curFolder->showFilesInTree(search_curFolder);

        SoundFile* fileToShow = (SoundFile*) ui->fileTree->topLevelItem(search_fileIndex);

        ui->fileTree->setCurrentItem( fileToShow);
        updateRevoicesTable_on_currentSoundChanged( (QTreeWidgetItem*) fileToShow);

        progressDialog->close();
        delete progressDialog;
    }
    else
    {
        qDebug() << "Gameloc::search: Поиск в папке " << search_curFolder->getName() << " не удался.";

        if( search_curFolder->getFoldersCount() )                       // Если есть подпапка
        {
            qDebug() << "Gameloc::search: Начинаю поиск в подпапке " << search_curFolder->getFolders().at(0)->getName();
            search_subdirIndexes.push_back(0);
            search_curFolder = search_curFolder->getFolders().at(0);    // Переходим к ней
        }
        else
        {
            qDebug() << "Gameloc::search: Подпапок не обнаружено. Выхожу из текущей папки, поскольку она проверена";

            search_subdirIndexes.removeLast();
            search_subdirIndexes.last()++;

            search_curFolder = search_curFolder->getParentFolder();

            if( search_subdirIndexes.last() != search_curFolder->getFoldersCount())
            {
                search_curFolder = search_curFolder->getFolders().at(search_subdirIndexes.last());
                search_subdirIndexes.push_back(0);
            }
            else
            {
                while(search_subdirIndexes.last() == search_curFolder->getFoldersCount())
                {
                    if( !search_curFolder->getParentFolder() )
                        break;

                    qDebug() << "Gameloc::search: В папке " << search_curFolder->getName() << "нет непроверенных подпапок, выхожу";
                    search_subdirIndexes.removeLast();
                    search_subdirIndexes.last()++;

                    search_curFolder = search_curFolder->getParentFolder();

                    if( search_subdirIndexes.last() != search_curFolder->getFoldersCount())
                    {
                        search_curFolder = search_curFolder->getFolders().at(search_subdirIndexes.last());
                        search_subdirIndexes.push_back(0);

                        break;
                    }

                }

                qDebug() << "Gameloc::search: Найдена непроверенная подпапка " << search_curFolder->getName();
            }

            if( !search_curFolder->getParentFolder())    // Если родительской папки нет, значит что проверены все папки
            {
                qDebug() << "Gameloc::search: Родительской папки нет. Значит поиск завершен.";

                if( search_somethingWasFounded )
                {
                    search_curFolder = activeGLR->getTree();
                    search_somethingWasFounded = false;     // Поскольку во время нажатия кнопки "Продолжить поиск" данные могли изменится, надо сбросить
                                                            // данную переменную, потому что может произойти зацикливание
                }
                else
                {
                    QMessageBox::information(this, "Поиск не удался", "Файлы с требуемыми параметрами не найдены");

                    progressDialog->close();
                    delete progressDialog;

                    searchTextChanged();    // Возвращаем режим кнопки поиска из "Искать далее" в "Поиск"
                    disconnect( t, SIGNAL(timeout()), this, SLOT(search()));
                }

            }
        }
    }
}

SoundFile* Gameloc::searchInCurFolder()
{
    /* При нахождении файла запоминается его индекс. При нажатии кнопки "Искать далее" индекс инкриментируется, по нему вычисляется с каким файлом будут сравниватся запросы, и сразу его обнуление
     * Условие поиска: Если индекс текущего файла больше чем индекс последнего файла.
     * */
    qDebug() << "Gameloc::searchInCurFolder: Поиск в папке " << search_curFolder->getName();
    qDebug() << "Gameloc::searchInCurFolder: Искомое имя: " << search_partOfFilename;
    qDebug() << "Gameloc::searchInCurFolder: Искомый комментарий: " << search_partOfCommentary;
    qDebug() << "Gameloc::searchInCurFolder: Искомые теги: ";

    for( int i = 0; i < search_tagList.count(); i++)
        qDebug() << "Gameloc::searchInCurFolder: " << i+1 << ": " << search_tagList.at(i);

    // ---------------------

    SoundFile* curFile;
    int foundedTags;

    for( int i = search_fileIndex+1; i < search_curFolder->getFilesCount(); i++)
    {
        curFile = search_curFolder->getFile(i);
        foundedTags = 0;

        if( search_compareStrings( search_partOfFilename,   curFile->getName() ) &&
            search_compareStrings( search_partOfCommentary, curFile->getCommentary()))
        {
            qDebug() << "Gameloc::searchInCurFolder: Комментарий и имя файла найдены. Проверяю теги";

            if( search_tagList.isEmpty() )
            {
                qDebug() << "Gameloc::searchInCurFolder: Тегов нет. Поиск завершен";
                search_fileIndex = i;
                return curFile;
            }
            else
            {
                for( int j = 0; j < search_tagList.count(); j++)
                {
                    qDebug() << "Gameloc::searchInCurFolder: Ищу тег " << search_tagList.at(j);

                    for( int k = 0; k < curFile->getTags().count(); k++)
                    {
                        if( curFile->getTags().at(k) == search_tagList.at(j))
                        {
                            qDebug() << "Gameloc::searchInCurFolder: Тег найден";
                            foundedTags++;
                            break;
                        }
                    }
                }

                qDebug() << "Gameloc::searchInCurFolder: Найдено " << foundedTags << " из " << search_tagList.count() << " тег(ов)";
                if( foundedTags == search_tagList.count())
                {
                    qDebug() << "Gameloc::searchInCurFolder: Все теги найдены";
                    search_fileIndex = i;
                    return curFile;
                }

                qDebug() << "Gameloc::searchInCurFolder: Найдены не все теги. Это не искомый файл.";
            }
        }
        search_fileIndex = -1;
    }

    return NULL;
}

bool Gameloc::search_compareStrings( QString searchRequest, QString string)
{
    qDebug() << "____________________________";
    qDebug() << "Gameloc::search_compareStrings: Запрос: " << searchRequest << ", Строка: " << string;

    if( searchRequest == "*" || searchRequest.isEmpty())
        return true;

    int requestIndex = 0, stringIndex = 0;
    for( ; requestIndex < searchRequest.count(); requestIndex++, stringIndex++)     // Проверяем каждый символ
    {
        qDebug() << "Gameloc::search_compareStrings: Повтор цикла";
        qDebug() << "Gameloc::search_compareStrings: requestIndex = " << requestIndex;
        qDebug() << "Gameloc::search_compareStrings: stringIndex =  " << stringIndex;
        qDebug() << "Gameloc::search_compareStrings: searchRequest[requestIndex] = " <<searchRequest[requestIndex];
        qDebug() << "Gameloc::search_compareStrings: string[stringIndex] =         " << string[stringIndex];

        if( searchRequest[requestIndex] == string[stringIndex] || searchRequest[requestIndex] == '?')
        {
            qDebug() << "Gameloc::search_compareStrings: " << searchRequest[requestIndex] << " == "
                                                           << string[stringIndex];
            continue;
        }
        else
        if( searchRequest[requestIndex] == '*')                        // * - означает любую последовательность символов, значит надо искать следующий за * символ в строке
        {
            if( requestIndex != searchRequest.count() -1)
            {
                qDebug() << "Gameloc::search_compareStrings: Обнаружена \'*\'. Надо искать в строке символ " << searchRequest[requestIndex+1] ;

                for( stringIndex; stringIndex < string.count(); stringIndex++)
                {
                    qDebug() << "Gameloc::search_compareStrings: Текущий символ - " << string[stringIndex];
                    if( searchRequest[requestIndex+1] == string[stringIndex] )
                    {
                        qDebug() << "Gameloc::search_compareStrings: Нужный символ найден";
                        stringIndex--;
                        break;
                    }
                }

                if( stringIndex == string.count() )
                {
                    qDebug() << "Gameloc::search_compareStrings: Нужный символ небыл найден";
                    return false;
                }
            }
            else
            {
                qDebug() << "Gameloc::search_compareStrings: Обнаружена \'*\' будущая последней в строке, прекращаю проверку";
                return true;    // Если * была последней, то искать ничего не надо
            }
        }
        else
            return false;   // Если символы не совпадают
    }

    return true;
}

void Gameloc::searchTextChanged()
{
    if( searchNext_mode )
    {
        searchAction->setIcon(QIcon(":/icons/search.png"));
        disconnect( searchAction, SIGNAL(triggered()), this, SLOT(search_continue()));
        connect(    searchAction, SIGNAL(triggered()),       SLOT(search_fromMainWindow()));

        searchNext_mode = false;
    }
}

void Gameloc::checkAvailabilityOfSearchRequest()
{
    searchAction->setDisabled(searchField->text().isEmpty());
}

void Gameloc::prepareTo_ExportToFolder()
{
    exportDialog = new ExportDialog(ExportDialog::ExportToFolder, this);
    exportDialog->show();

    connect( exportDialog, SIGNAL(readyToExport(QString,bool)), SLOT(exportToFolder_start(QString,bool)));
}

void Gameloc::exportToFolder_start(QString exportPath, bool mainFiles)
{
    QDir *d = new QDir;

    if( d->exists(exportPath))
    {
        this->exportPath = exportPath;
        this->mainFiles  = mainFiles;

        progressDialog = new ProgressDialog(this);
        progressDialog->setTitle("Экспорт");
        progressDialog->setText("Экспорт проекта " + activeGLR->getProjectName());
        progressDialog->setMaxProgress( activeGLR->getTotalFiles() );
        progressDialog->setProgress(0);
        progressDialog->hideFullProgress();
        progressDialog->show();

        export_curFolder = activeGLR->getTree();
        export_fileIndex = 0;
        export_subdirIndexes << 0;

        t->start(1);
        connect( t, SIGNAL(timeout()), SLOT(exportToFolder_cycle()));
    }
    else
        QMessageBox::critical(this, "Ошибка экспорта", "Указанной папки несуществует, экспорт не будет произведен");
}

void Gameloc::exportToFolder_cycle()
{
    // BUG: Ошибка при экспорте главных переозвучек.

    if( export_curFolder)
    if( export_fileIndex != export_curFolder->getFilesCount())
    {
        progressDialog->setText("Экспорт проекта " + activeGLR->getProjectName() +
                                tr("\nСкопировано %1 из %2").arg(progressDialog->getProgress()).arg(activeGLR->getTotalFiles()));

        SoundFile *curSound = export_curFolder->getFile( export_fileIndex );
        QDir *d = new QDir;                                                     // Для создания конечного пути копирования

        if( mainFiles )
        {
            qDebug() << "Gameloc::exportToFolder_cycle: Выбран экспорт только основных переозвучек.";
            qDebug() << "Gameloc::exportToFolder_cycle: Начинаю поиск основной переозвучки файла " << curSound->getName();

            Revoice *mainRevoice = NULL;

            int index;
            for( index = 0; index < curSound->getRevoicesCount(); index++)
                if( curSound->getRevoice(index)->isGeneral() )
                    if( !mainRevoice )
                    {
                        mainRevoice = curSound->getRevoice(index);
                        break;
                    }

            if( mainRevoice )   // Если основная переозвучка найдена
            {
                QString copyTo = exportPath;
                copyTo += mainRevoice->getPath();
                copyTo = copyTo.remove(activeGLR->getTempPath());
                copyTo = copyTo.remove( tr("/revoices/%1").arg( mainRevoice->getFilename()));

                qDebug() << "Gameloc::exportToFolder_cycle: Копирование переозвучки из " << mainRevoice->getPath() << " в " << copyTo;

                qDebug() << "Gameloc::exportToFolder_cycle: Создаю папку " << QString(copyTo).remove(curSound->getName());
                d->mkpath( QString(copyTo).remove(curSound->getName()));

                QFile::remove( copyTo );
                if( ! QFile::copy( mainRevoice->getPath(), copyTo))
                {
                    QMessageBox::critical(this, "Ошибка при экспорте", tr("Не удалось скопировать файл %1 в %2").arg(mainRevoice->getPath())
                                                                                                                .arg(copyTo));
                    disconnect(t, SIGNAL(timeout()), this, SLOT(exportToFolder_cycle()));
                }
                else
                    qDebug() << "Gameloc::exportToFolder_cycle: Скопировано успешно";
            }
            else    // Если основная переозвучка не найдена
            {
                qDebug() << "Gameloc::exportToFolder_cycle: Основная переозвучка не найдена. Копирую оригинальный файл";
                qDebug() << "Gameloc::exportToFolder_cycle: из " << curSound->getPathToOrig()
                         << " в " << exportPath + curSound->getPath().remove(activeGLR->getTempPath());

                qDebug() << "Gameloc::exportToFolder_cycle: Создаю папку " << exportPath + curSound->getPath().remove(activeGLR->getTempPath()).remove(curSound->getName());
                d->mkpath( exportPath + curSound->getPath().remove(activeGLR->getTempPath()).remove(curSound->getName()));

                QFile::remove(exportPath + curSound->getPath().remove(activeGLR->getTempPath()));
                if( ! QFile::copy(curSound->getPathToOrig(), exportPath + curSound->getPath().remove(activeGLR->getTempPath()) ))
                {
                    QMessageBox::critical(this, "Ошибка при экспорте", tr("Не удалось скопировать файл %1 в %2").arg(curSound->getPathToOrig())
                                                                                                                .arg(exportPath + curSound->getPath().remove(activeGLR->getTempPath())));
                    disconnect(t, SIGNAL(timeout()), this, SLOT(exportToFolder_cycle()));
                }
                else
                    qDebug() << "Gameloc::exportToFolder_cycle: Скопировано успешно";
            }
        }
        else    // Если требуется экспортировать только оригинальную озвучку
        {
            qDebug() << "Gameloc::exportToFolder_cycle: Выбран экспорт только оригинальных озвучек. Копирую оригинальный файл";
            qDebug() << "Gameloc::exportToFolder_cycle: из " << curSound->getPathToOrig()
                     << " в " << exportPath + curSound->getPath().remove(activeGLR->getTempPath());

            qDebug() << "Gameloc::exportToFolder_cycle: Создаю папку " << exportPath + curSound->getPath().remove(activeGLR->getTempPath()).remove(curSound->getName());
            d->mkpath( exportPath + curSound->getPath().remove(activeGLR->getTempPath()).remove(curSound->getName()));

            QFile::remove(exportPath + curSound->getPath().remove(activeGLR->getTempPath()));
            if( ! QFile::copy(curSound->getPathToOrig(), exportPath + curSound->getPath().remove(activeGLR->getTempPath()) ))
            {
                QMessageBox::critical(this, "Ошибка при экспорте", tr("Не удалось скопировать файл %1 в %2").arg(curSound->getPathToOrig())
                                                                                                            .arg(exportPath + curSound->getPath().remove(activeGLR->getTempPath())));
                disconnect(t, SIGNAL(timeout()), this, SLOT(exportToFolder_cycle()));
            }
            else
                qDebug() << "Gameloc::exportToFolder_cycle: Скопировано успешно";
        }

        progressDialog->incrementProgress();
        export_fileIndex++;
    }

    if( activeGLR->getTotalFiles() == progressDialog->getProgress() || export_curFolder == NULL)
    {
        disconnect(t, SIGNAL(timeout()), this, SLOT(exportToFolder_cycle()));

        QMessageBox::information(this, "Завершено", tr("Скопировано %1 из %2").arg(progressDialog->getProgress())
                                                                            .arg(activeGLR->getTotalFiles()));

        progressDialog->close();
        delete progressDialog;
    }

    if( export_curFolder)
    if( export_fileIndex == export_curFolder->getFilesCount())
    {
        export_fileIndex = 0;

        if( export_curFolder->getFoldersCount() )   // Если есть подпапки
        {
            while( export_curFolder->getFoldersCount())
            {
                export_curFolder = export_curFolder->getFolders().at(0);
                export_subdirIndexes.push_back(0);
            }
        }
        else
        {
            export_curFolder = export_curFolder->getParentFolder();

            export_subdirIndexes.removeLast();

            if( export_subdirIndexes.count() )
                export_subdirIndexes.last()++;

            if( export_curFolder->getFoldersCount() != export_subdirIndexes.last())
            {
                export_curFolder = export_curFolder->getFolders().at(export_subdirIndexes.last());
                export_subdirIndexes << 0;
            }
            else
            {
                while( export_subdirIndexes.last() == export_curFolder->getFoldersCount())
                {
                    export_curFolder = export_curFolder->getParentFolder();

                    if( export_curFolder == activeGLR->getTree())
                        qDebug() << "???";

                    export_subdirIndexes.removeLast();

                    if( export_subdirIndexes.count() )
                        export_subdirIndexes.last()++;
                    else
                        break;

                    if( export_subdirIndexes.count() <= 1 &&
                        export_curFolder->getFoldersCount() == export_subdirIndexes.last())     // Если скопированы все папки
                        break;


                    if( export_curFolder->getFoldersCount() != export_subdirIndexes.last())
                    {
                        export_curFolder = export_curFolder->getFolders().at(export_subdirIndexes.last());
                        export_subdirIndexes << 0;
                        break;
                    }
                }
            }
        }
    }
}

/************ Экспорт
Если только оригинальные
    Копирование оригинального
Если только помеченные основными
    Поиск помеченного
    Если найден
        Копирование
    Иначе
        Копирование оригинального

Инкримент прогресса
Инкримент индекса файлов
Если индекс == количество файлов
    Сброс индекса файлов
    Если есть подпапка
        Пока есть подпапки
            Переход в подпапку
            добавление индекса к вектору
    Иначе
        Выход из текущей папки
        Удаление последнего индекса
        Инкримент последнего индекса
        Пока индекс == количеству папок
            Выход из текущей папки
            Удаление последнего индекса
            Инкримент последнего индекса
*/

// TODO: Удаление файлов и папок из GLR
// TODO: Экспорт в архив
// TODO: Экспорт в самораспаковывающийся архив
// TODO: Экспорт в папку
// TODO: Редактирование свойств локализации
// TODO: Импорт файлов из папки
// TODO: Перевод через Яндекс.Переводчик
// TODO: Меню справки
// TODO: Добавление кнопок программ
// TODO: При перемещении ползунка изменение позиции воспроизведения
// TODO: При несоответствии длины переозвучки длине оригинала окрашивать клетку времени в красный цвет
// TODO: Если во временной папке есть неудаленный распакованный проект, предлогать сохранить
// TODO: Настройки программы

